class Card
  #constants
  attr_accessor :suit, :value     #get and set for suit and value

  CLUB="club"
  DIAMOND="diamond"
  HEART="heart"
  SPADE="spade"


  #instance variables
  @suit  #string, the color of the card
  @value  #an integer, value of the card 2<=value<=14

  #instance methods
  private

    def initialize (suit,value)
      @suit=suit
      @value=value
    end

  public

    def valueToString

      if @value==10
        return "T"
      end
      if @value==11
        return "J"
      end
      if @value==12
        return "Q"
      end
      if @value==13
        return "K"
      end
      if @value==14
        return "A"
      end
      if @value<10
        return @value.to_s
      end
    end    #of valueToString

    def to_s
      "#{@suit.to_s} " + self.valueToString
    end

    def <=>(aCard)
      if (self.suit==aCard.suit)
        if (self.value<aCard.value)
          return -1
        else
          return 1
        end
      end

      if self.suit<aCard.suit then return -1
      elsif self.suit>aCard.suit then return 1
      end

    end
end #end class Card


class CardHand<Array
  public
    def getCards(aDeck)
      13.times{|i| self.push(aDeck<<aDeck.next) }
      self.sort!
    end

    #similar to the to_s method in cardDeck
    def to_s
      self.inject("") {|result,card| result + "(#{card.to_s}) "}
    end

end #of class

class CardDeck<Array

  private
    def initialize
      @cardDeck=initSuite(Card::SPADE)
      @cardDeck+=initSuite(Card::HEART)
      @cardDeck+=initSuite(Card::DIAMOND)
      @cardDeck+=initSuite(Card::CLUB)
    end

    #parameter is aSuit. Creates card with values 2-14 for the given suit
    def initSuite (aSuit)

      self.push(Card.new(aSuit,2))
      self.push(Card.new(aSuit,3))
      self.push(Card.new(aSuit,4))
      self.push(Card.new(aSuit,5))
      self.push(Card.new(aSuit,6))
      self.push(Card.new(aSuit,7))
      self.push(Card.new(aSuit,8))
      self.push(Card.new(aSuit,9))
      self.push(Card.new(aSuit,10))
      self.push(Card.new(aSuit,11))
      self.push(Card.new(aSuit,12))
      self.push(Card.new(aSuit,13))
      self.push(Card.new(aSuit,14))
    end

    #swaps the card in Index1 and Index2
    def swap(anIndex1, anIndex2)
      temp=self[anIndex1]
      self[anIndex1]=self[anIndex2]
      self[anIndex2]=temp

    end

  public

    #deals the next card and removes it from self
    def next
      return @cardDeck.pop
    end

    #shuffles the deck by using the swap method 26 times
    def shuffle
      srand()
      26.times do |i|
        i1=rand(52)
        i2=rand(52)
        swap(i1,i2)
      end
    end #shuffle

    def to_s
      self.inject("") {|result,card| result + "(#{card.to_s}) "}
    end
end  #end class

class Bridge
  attr_reader :west, :north, :east, :south, :deck

  def initialize
    @deck = CardDeck.new
    @deck.shuffle
    @west = CardHand.new.getCards(@deck)
    @north = CardHand.new.getCards(@deck)
    @east = CardHand.new.getCards(@deck)
    @south = CardHand.new.getCards(@deck)
  end

  private :initialize


end

#test for card class
 puts("test for card class")
 c1 = Card.new(Card::DIAMOND,5)
 puts c1.to_s
 c2 = Card.new(Card::DIAMOND, 10)
 puts c2.to_s
 c3 = Card.new(Card::HEART, 14)
 puts c3.to_s
 puts(c1 <=> c2)
 puts(c3 <=> c1)

#test for CardDeck class
puts("test for cardDeck class")
deck = CardDeck.new
puts deck.to_s
puts
deck.shuffle
puts deck.to_s

#FINAL TESTING
puts("Final testing")
br = Bridge.new
puts "West: #{br.west.to_s}"
puts
puts "North: #{br.north.to_s}"
puts
puts "East: #{br.east.to_s}"
puts
puts "South: #{br.south.to_s}"

